-
Notifications
You must be signed in to change notification settings - Fork 80
Made the logical shift / artihmetic shift not rely on signs of intigers #749
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for making this PR!
let b_size = b_type.get_size(); | ||
match a_size.cmp(&b_size) { | ||
std::cmp::Ordering::Less => { | ||
let a = self.context.new_cast(self.location, a, b_type); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a debug_assert!()
that checks that the sign of a
and b
is the same here?
} | ||
std::cmp::Ordering::Equal => a >> b, | ||
std::cmp::Ordering::Greater => { | ||
let b = self.context.new_cast(self.location, b, a_type); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And here as well.
std::cmp::Ordering::Less => { | ||
let a = self.context.new_cast(self.location, a, b_type); | ||
a >> b | ||
} | ||
std::cmp::Ordering::Equal => a >> b, | ||
std::cmp::Ordering::Greater => { | ||
let b = self.context.new_cast(self.location, b, a_type); | ||
a >> b | ||
} | ||
let (a, a_type) = match (shift_kind, a_type.is_signed(self.cx)) { | ||
(ShiftKind::Logical, true) => { | ||
let a_type = a_type.to_unsigned(self.cx); | ||
(self.gcc_int_cast(a, a_type), a_type) | ||
} | ||
(ShiftKind::Logical, false) => (a, a_type), | ||
(ShiftKind::Arithmetic, true) => (a, a_type), | ||
(ShiftKind::Arithmetic, false) => { | ||
let a_type = a_type.to_signed(self.cx); | ||
(self.gcc_int_cast(a, a_type), a_type) | ||
} | ||
}; | ||
let (b, b_type) = match (shift_kind, b_type.is_signed(self.cx)) { | ||
(ShiftKind::Logical, true) => { | ||
let b_type = b_type.to_unsigned(self.cx); | ||
(self.gcc_int_cast(b, b_type), b_type) | ||
} | ||
(ShiftKind::Logical, false) => (b, b_type), | ||
(ShiftKind::Arithmetic, true) => (b, b_type), | ||
(ShiftKind::Arithmetic, false) => { | ||
let b_type = b_type.to_signed(self.cx); | ||
(self.gcc_int_cast(b, b_type), b_type) | ||
} | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please add a comment to explain that this casts to unsigned if needed to do a logical shift and to signed if needed to do an arithmetic shift?
@@ -14,7 +14,7 @@ use rustc_middle::ty::{self, Ty}; | |||
use rustc_target::callconv::{ArgAbi, ArgAttributes, FnAbi, PassMode}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be easy to add a test for this fix?
Co-authored-by: antoyo <[email protected]>
Currently,
ashr
&lshr
share the same implementation, and the shift type is guessed based on the sign of the type.This is incorrect W.R.T.
cg_ssa
semantics(type don't have signs, operations do), and has caused silent miscompilations in the past(cg_ssa
requested a logcal shift, butcg_gcc
inserted an arithmetic one). This bug was pretty rare, but was still a miscompilation.This PR fixes that bug, by introducing a new parameter(
ShiftKind
) togcc_shr
(renamed fromgcc_lshr
). This allows both shift kinds to still share an implementation, while being very explicit about the requested shift.